#!/usr/bin/env python

import sys, time
from optparse import OptionParser
from dpkt import bgp, mrt
from pybgpdump import BGPDump
#import dnet
import socket
from struct import unpack, pack 

def aspath_to_str(as_path):
    str = ''
    for seg in as_path.segments:
        if seg.type == bgp.AS_SET:
            start = '['
            end = '] '
        elif seg.type == bgp.AS_SEQUENCE:
            start = ''
            end = ' '
        else:
            start = '?%d?' % (seg.type)
            end = '? '
        str += start
        for AS in seg.path:
            str += '%d ' % (AS)
        str = str[:-1]
        str += end
    str = str[:-1]
    return str

def origin_to_str(origin):
    str = ''
    if origin.type == bgp.ORIGIN_IGP:
        str = 'IGP'
    elif origin.type == bgp.ORIGIN_EGP:
        str = 'EGP'
    elif origin.type == bgp.INCOMPLETE:
        str = 'INCOMPLETE'
    return str

def communities_to_str(communities):
    str = ''
    for comm in communities.list:
        try:
            str += '%d:%d ' % (comm.asn, comm.value)
        except AttributeError:
            str += '%d ' % (comm.value)
    str = str[:-1]
    return str

def clusterlist_to_str(cluster_list):
    str = ''
    for cluster in cluster_list.list:
        str += '%s ' % socket.inet_ntoa(cluster)
    str = str[:-1]
    return str

def main():
    parser = OptionParser()
    parser.add_option('-i', '--input', dest='input', default='sample.dump.gz',
                      help='read input from FILE', metavar='FILE')
    parser.add_option("-m", "--machine", action="store_true", dest="machine",
                      default=True, help="output in machine-readable form")
    parser.add_option("-a", "--asn", dest="asn",
                      default="")
    parser.add_option("-d", "--debug", dest="debug",
                      default=False,action="store_true",help="output in machine-readable form")                  
    (options, args) = parser.parse_args()

    out = sys.stdout.write
    dump = BGPDump(options.input)
    asn_list=[]
    for i in open(options.asn):
        i=i.strip("\r\n")
        if i.isdigit():
            asn_list.append(int(i))
    if options.debug:
        for i in asn_list:
          sys.stderr.write(str(i))
    for mrt_h, bgp_h, bgp_m in dump:
        next_hop = 'none'
        atomic_aggregate = 'NAG'
        local_pref = multi_exit_disc = '0'
        origin = as_path = communities = aggregator = ''

        for attr in bgp_m.update.attributes:
            if attr.type == bgp.AS_PATH:
                as_path = aspath_to_str(attr.as_path)
            elif attr.type == bgp.ORIGIN:
                origin = origin_to_str(attr.origin)
            elif attr.type == bgp.NEXT_HOP:
                next_hop = socket.inet_ntoa(pack('>L', attr.next_hop.ip))
            elif attr.type == bgp.LOCAL_PREF:
                local_pref = '%d' % (attr.local_pref.value)
            elif attr.type == bgp.MULTI_EXIT_DISC:
                multi_exit_disc = '%d' % (attr.multi_exit_disc.value)
            elif attr.type == bgp.COMMUNITIES:
                communities = communities_to_str(attr.communities)
            elif attr.type == bgp.ATOMIC_AGGREGATE:
                atomic_aggregate = 'AG'
            elif attr.type == bgp.AGGREGATOR:
                aggregator = socket.inet_ntoa(pack('>L', attr.aggregator.ip))
        #BGP4MP|1157798700|
        #time_str = '%s|%s' % ('BGP4MP', mrt_h.ts)
        #3333|219.64.224.0/23|3333 1103 3549 4755|IGP|193.0.0.56|0|0||NAG|219.64.255.194|
        #attrs = '%s|%s|%s|%s|%s|%s|%s|%s|' % \
        #       (as_path, origin, next_hop, local_pref, multi_exit_disc,
                # communities, atomic_aggregate, aggregator)
                
                
#BGP4MP|1157798864|A|208.51.134.248|3549|199.181.158.0/23|3549 701 7260 4595|INCOMPLETE|208.51.134.248|0|2728|3549:2174 3549:30840|NAG||

        #print asn_list
        for route in bgp_m.update.announced:
            src_as_path=bgp_h.src_as
            if options.debug:
                sys.stderr.write(str(src_as_path,type(src_as_path)))
                raw_input()
            #print src_as_path
            if src_as_path in asn_list:
                #99.181.158.0/23|3549|3549 701 7260 4595
                out_str = "%s/%s|%s|%s\n"% \
                          (socket.inet_ntoa(route.prefix), route.len,                           src_as_path, as_path)
                out(out_str)
              #A|193.0.0.56|
            #out('%s|A|%s|%d|%s/%d|%s\n' % 
            #    (time_str, socket.inet_ntoa(pack('>L', bgp_h.src_ip)), bgp_h.src_as,
            #     socket.inet_ntoa(route.prefix), route.len, attrs))
#socket.inet_ntoa(pack('>L', route.prefix))


#        for route in bgp_m.update.withdrawn:
#            out('%s|W|%s|%d|%s/%d\n' % 
#                (time_str, socket.inet_ntoa(pack('>L', bgp_h.src_ip)), bgp_h.src_as,
#                 socket.inet_ntoa( route.prefix), route.len))

if __name__ == '__main__':
    main()
